#ifndef _EVENTLOOP_H
#define _EVENTLOOP_H
#include "Acceptor.hpp"
#include <header.h>
#include <map>
#include <vector>
#include <sys/eventfd.h>
#include <unistd.h>
#include <memory>
#include <mutex>
#include <functional>
using std::function;
using std::unique_lock;
using std::mutex;
using std::vector;
using std::map;
using Functor = function<void()>;
class TcpConnection;
using TcpConnectionPtr = std::shared_ptr<TcpConnection>;
using TcpConnectionCall = function<void(TcpConnectionPtr)>;
class EventLoop
{
public:
    EventLoop(Acceptor & acceptor):_epfd(createEpfd())
                                   ,_eventfd(createEventfd())
                                   ,evArr(1000)
                                   , _acceptor(acceptor)
    {
        addEpollReadEvent(_acceptor.fd());
        addEpollReadEvent(_eventfd);
    }
    ~EventLoop() {
        if(_epfd > 0){
            close(_epfd);
        }
        if(_eventfd>0){
            close(_eventfd);
        }
    }

    void setAllCallBack(TcpConnectionCall &&onConnect
                        ,TcpConnectionCall&& onMessage
                        ,TcpConnectionCall&& onClose){
        _onConnect = std::move(onConnect);
        _onMessage = std::move(onMessage);
        _onClose = std::move(onClose);
    }
    void loop();
    void unloop(){
        isLoop = false;
    }

    void runInLoop(Functor && );

private:
    void handleNewConnect();
    void handleMessage(int fd);

    int createEpfd();
    void waitEpollFd();

    void addEpollReadEvent(int);
    void delEpollReadEvent(int);

    int createEventfd();
    void wakeup();
    void handleReadEvent();
    void doFunctors();

private:
    bool isLoop = true;
    int _epfd;
    int _eventfd;
    vector<struct epoll_event> evArr;
    vector<Functor> _functors;
    Acceptor& _acceptor;
    map<int,TcpConnectionPtr> tcpMap;
    TcpConnectionCall _onConnect;
    TcpConnectionCall _onMessage;
    TcpConnectionCall _onClose;
    mutex _mutex;
};
#endif

